<?php

class CaptchaGenerator
{
    var $fontsDirectory = "";

    var $rotateAngleMin = 0;
    var $rotateAngleMax = 20;
    
    private $charColor = "202020";    
    private $backgroundColor = "EEEEEE";    
    
    private $sizeCoefficient = 0.85;
    private $fontsFileName = "GOTHIC.TTF";

    /**
    * Initialize chars color
    *
    * @param string $newColor
    * 
    */
    public function SetCharsColor( $newColor )
    {
        $this->charColor = $newColor;
    }
    
    /**
    * Initialize background color
    *
    * @param string $newColor
    * 
    */
    public function SetBackGroundColor( $newColor )
    {
        $this->backgroundColor = $newColor;        
    }
    
    /**
    *
    * @return array
    */    
    private function SplitColor( $color )
    {
        $splitedColor = array();
        $splitedColor["red"] = hexdec(substr( $color, 0, 2) );
        $splitedColor["green"] = hexdec(substr( $color, 2, 2) );
        $splitedColor["blue"] = hexdec(substr( $color, 4, 2) );
        return $splitedColor;
    }
    
    /**
     * Initialize size of chars:
     *   size = image height * coefficient
     *
     * @param int $newSizeCoefficient
     *
     */    
    public function SetSizeCoefficient( $newSizeCoefficient )
    {
        $this->sizeCoefficient = $newSizeCoefficient;
    }
    
    /**
    * Initialize fonts file name
    *
    * @param string $newFontsFileName
    * 
    */
    public function SetFontsFileName( $newFontsFileName )
    {
        $this->fontsFileName = $newFontsFileName;       
    }
    
    public function GenerateCode( $codeLength )
    {
        $captchaCharSet = "23456789ABCDEFGHJKLMNOPQRST";
        $code = "";
        for ($i = 0; $i < $codeLength; $i++)
        {
            $code .= $captchaCharSet[rand( 0, ( strlen( $captchaCharSet ) - 1 ) )];
        }
        return $code;
    }

    public function GenerateAndOutputImage( $chars, $width, $height )
    {
        $charsCount = strlen( $chars );

        $image = imagecreatetruecolor( $width, $height );
        $splitedColor = $this->SplitColor($this->backgroundColor);
        $bgColor = imagecolorresolve( $image, $splitedColor["red"], $splitedColor["green"], $splitedColor["blue"]);
        ImageFill( $image, 0, 0, $bgColor );

        for ( $i = 0; $i < $charsCount; $i++ )
        {   

            $this->WriteCharacter( $image, $chars[$i], $i, $charsCount );
                    
        }
        
        imagefilter( $image, IMG_FILTER_GAUSSIAN_BLUR );        
        imagefilter( $image, IMG_FILTER_GAUSSIAN_BLUR );               

        Header( "Content-Type: image/png" );
        imagepng( $image );
        imagedestroy( $image );
    }

    public function GeneratePrivateCode($captchaCode)
    {
        $secretString = "A very, nano very secret string which is used to generate a md5-key!";
        return strtolower( substr( md5( md5( $secretString ).$captchaCode ), 16 - 5 / 2, 4 ) );
    }    
    
    private function WriteCharacter( $image, $char, $charIndex, $charsCount )
    {
        $width  = imagesx( $image );
        $height = imagesy( $image ); 

        $startFrom = $width / 10;

        $charWidth  = $width / $charsCount;
        $charHeight = $height / 2;
        $splitedColor = $this->SplitColor($this->charColor);

        $text         = $char;
        $size         = $charHeight * $this->sizeCoefficient;
        $angle        = rand( $this->rotateAngleMin, $this->rotateAngleMax );
        $x            = $startFrom + $charIndex * $charWidth;
        $y            = $size + ( $height - $size ) / 2;
        $color        = ImageColorResolve( $image, $splitedColor["red"], $splitedColor["green"], $splitedColor["blue"] );
        $fontFile     = $this->GetFontFile();               
                
        ImageTTFText( $image, $size, $angle, $x, $y, $color, $fontFile, $text );
    }

    protected function GetFontFile()
    {
        $fontFile = $this->fontsDirectory . "/" . $this->fontsFileName;
        return $fontFile;
    }
}

?>